#include <iostream>
#include <future>

// std::function 包装器与 std::packaged_task 有些相似:
// 1. 二者都可以封装可调用对象，并允许后续执行
// 区别:
// std::function 是为了提供一个统一的方式来处理任何可调用对象
// std::packaged_task 主要用于异步任务的管理，尤其是与线程和 std::future 结合使用
// std::function 本身不提供结果处理机制。(更为通用)
// std::packaged_task 结合 std::future，可以捕获返回任务的执行结果

// 如何理解future?
// future内部并不会创建线程, promise和package_task执行的任务结果会放到future这个类的对象中, 它更像是中间传递数据的功能

int Add(int num1, int num2)
{
    return num1 + num2;
}

int main()
{

    // std::packaged_task<int(int, int)> task(Add);
    // std::future<int> fu = task.get_future();

    // task(11, 22);  //task可以当作一个可调用对象来调用执行任务
    // 但是它又不能完全的当作一个函数来使用
    // std::async(std::launch::async, task, 11, 22); // 报错
    // std::thread thr(task, 11, 22); // 报错

    // 我们可以把task定义成为一个指针，传递到线程中，然后进行解引用执行
    // 但是如果单纯指针指向一个对象，存在生命周期的问题，很有可能出现风险
    // 思想就是在堆上new对象，用智能指针管理它的生命周期
    auto ptask = std::make_shared<std::packaged_task<int(int, int)>>(Add);
    std::future<int> fu = ptask->get_future();
    std::thread thr([ptask]()
                    { (*ptask)(11, 22); });
    int sum = fu.get();
    std::cout << sum << std::endl;
    // thr.join();
    return 0;
}